package com.example.a2032.Utils;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.WifiConfiguration;
import android.text.TextUtils;
import android.util.Log;

import com.amap.api.fence.GeoFence;
import com.amap.api.fence.GeoFenceListener;
import com.example.a2032.BuildConfig;
import com.example.a2032.MyApp;
import com.example.a2032.activity.BaseActivity;
import com.example.a2032.activity.BpMeasureActivity;
import com.example.a2032.activity.EcgMeasureActivity;
import com.example.a2032.activity.FindPhoneActivity;
import com.example.a2032.activity.HeartRateMeasureActivity;
import com.example.a2032.activity.Spo2MeasureActivity;
import com.example.a2032.db.DataDbHelper;
import com.example.a2032.db.dao.DeviceInfoDao;
import com.example.a2032.entity.ActionData;
import com.example.a2032.entity.BleData;
import com.example.a2032.entity.DeviceInfo;
import com.example.a2032.entity.FindWatchBean;
import com.example.a2032.entity.ImResultData;
import com.example.a2032.entity.JstyleClock;
import com.example.a2032.entity.RealTimeData;
import com.example.a2032.entity.SmsInfo;
import com.example.a2032.entity.TaskBindData;
import com.example.a2032.entity.TaskData;
import com.example.a2032.entity.TaskUnBindData;
import com.example.a2032.net.CallLogs;
import com.example.a2032.net.NetWorkUtil;
import com.example.a2032.net.jstylenet.BindContactData;
import com.example.a2032.net.jstylenet.ContactData;
import com.example.a2032.net.jstylenet.DeleteClockData;
import com.example.a2032.net.jstylenet.DeleteContact;
import com.example.a2032.net.jstylenet.MoniData;
import com.example.a2032.net.jstylenet.PsmData;
import com.example.a2032.net.jstylenet.SetClockData;
import com.example.a2032.net.jstylenet.ElectronicFenceData;
import com.example.a2032.net.jstylenet.JstyleConst;
import com.example.a2032.net.jstylenet.NetSendUtils;
import com.example.a2032.net.jstylenet.RealTimeMeasureCmd;
import com.example.a2032.net.jstylenet.StepGoal;
import com.example.a2032.net.jstylenet.UploadCallLogs;
import com.example.a2032.net.jstylenet.WifiSetData;
import com.example.a2032.net.jstylenet.jstyleResponse.ConnectResponse;
import com.example.a2032.net.jstylenet.jstyleResponse.HistoryDataResponse;
import com.example.a2032.net.jstylenet.jstyleResponse.JstyleResponse;
import com.example.a2032.net.jstylenet.jstyleResponse.RegisterResponse;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;


import java.lang.reflect.Type;
import java.net.URI;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.WebSocket;

public class WebSocketUtils {

    private static final String TAG = "WebSocketUtil";
    private ExecutorService mExecutorService;
    private WebSocketClient webSocketClient;
    private boolean isStart;
    Disposable reconnectWifiObservable;
    Disposable heartPackageObservable;
    Disposable uploadHistoryObservable;
    String testUri = "ws://192.168.0.111/wsj2032test";
    //ws://hkws.le-young.com:10500/j2032
    String testWebUri = "ws://hkws.le-young.com:10500/j2032";
    Context context;

    public boolean isMeasuring() {
        return isMeasuring;
    }

    public void setMeasuring(boolean measuring) {
        isMeasuring = measuring;
    }

    private boolean isMeasuring;
    private static WebSocketUtils ourInstance;

    public static WebSocketUtils getInstance() {
        return ourInstance;
    }

    public static void init(Context context) {
        if (ourInstance == null) {
            synchronized (WebSocketUtils.class) {
                if (ourInstance == null) {
                    ourInstance = new WebSocketUtils(context);
                }
            }
        }
    }

    OkHttpClient mClient;
    Request mRequest;
    boolean isWebConnected;

    private WebSocketUtils(Context context) {
        this.context = context;

        mExecutorService = Executors.newCachedThreadPool();
        mExecutorService.execute(new connectService());
        // initOkHttpClient();
    }


    public void toConnect() {
        String user = SharedPreferenceUtils.getSpString(SharedPreferenceUtils.watchId);
        //现在imei固定，设置一个假的id调试
        // user="263515630823673856";
        if (TextUtils.isEmpty(user)) {
            String imei = Utils.getIMEI(context);
            String phone = Utils.getPhone(context);
            DeviceInfoDao deviceInfoDao = DataDbHelper.getInstance(context).getDeviceInfoDao();
            DeviceInfo deviceInfo = null;
            if (deviceInfoDao != null) {
                deviceInfo = deviceInfoDao.loadDeviceInfo();
            }
//            String address = "aa:55:55";
//            if (deviceInfo == null) {
//                Log.i(TAG, "onOpen: getMac");
//                SerialPortUtil.getInstance().sendSerialPort(BleSdk.getDeviceMac());
//            } else {
            //  address = deviceInfo.getDeviceAddress();
            sendMsg(NetSendUtils.registerDevice(imei, "", ""));
            // }
        } else {
            sendMsg(NetSendUtils.connect(user));
        }

    }

    private class connectService implements Runnable {
        @Override
        public void run() {
            try {
                webSocketClient = new WebSocketClient(new URI(BuildConfig.needWifi ? testUri : testWebUri)) {
                    @Override
                    public void onOpen(ServerHandshake handshakedata) {
                        Log.i(TAG, "onOpen: ");
                        toConnect();
                        unsubscribe(reconnectWifiObservable);
                    }

                    @Override
                    public void onMessage(String message) {
                        Log.i(TAG, "onMessage:加密之前 " + message);

                        try {
                            //resolveData(AesTest.Decrypt(message));
                            resolveData(message);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }

                    @Override
                    public void onClose(int code, String reason, boolean remote) {
                        Log.i(TAG, "onClose: " + code + " " + reason);
                        isStart = false;
                        startReconnectWifiObservable();
                        unsubscribe(heartPackageObservable);
                        unsubscribe(uploadHistoryObservable);
                    }

                    @Override
                    public void onError(Exception ex) {
                        ex.printStackTrace();
                        //   Log.i(TAG, "onError: " + ex.printStackTrace(););

                    }
                };

                webSocketClient.connect();
                Log.i(TAG, "run: ");
            } catch (Exception e) {
                Log.e(TAG, ("connectService:" + e.getMessage()));
            }
        }
    }

    private void resolveData(String message) {
        Log.i(TAG, "resolveData: 解析后 "+message);
        Gson gson = new Gson();
        JstyleResponse jstyleResponse = gson.fromJson(message, JstyleResponse.class);
        String type = jstyleResponse.getType();
        JstyleResponse.ExtendBean extendBean = jstyleResponse.getExtend();
        String from = "";
        if (extendBean != null) {
            from = extendBean.getFrom();
        }
        switch (type) {
            case JstyleConst.TYPE_Task:
                List<TaskData> taskDataList= getResponseData(new TypeToken<JstyleResponse<List<TaskData>>>() {
                }.getType(), message);
                Gson gson1 = new Gson();
                List<String>idList=new ArrayList<>();
                for(TaskData taskData:taskDataList){
                    String taskBindData = taskData.getContent();
                    String taskType = taskData.getTaskType();
                    String taskId=taskData.getId();
                    if (taskType.equals(JstyleConst.Task_Bind)) {
                        BindContactData bindContactData = gson1.fromJson(taskBindData, BindContactData.class);
                        ContactUtils.addContact(context, bindContactData);
                    } else if (taskType.equals(JstyleConst.Task_MemberUnbind) || taskType.equals(JstyleConst.Task_AdminUnbind)) {
                        TaskUnBindData taskUnBindData=gson1.fromJson(taskBindData, TaskUnBindData.class);
                        ContactUtils.deleteContact(context, taskUnBindData.getPhone());
                    } else if (taskType.equals(JstyleConst.Task_AdminDisband)) {
                      //  ContactUtils.deleteAllContact(context);
                        clearData();
                    }
                    idList.add(taskId);
                }
                sendMsg(NetSendUtils.resultResponseWithId(JstyleConst.TYPE_Task, idList, from));
                break;
            case JstyleConst.TYPE_Clear:
                clearData();
                break;
            case JstyleConst.TYPE_IM:
                ImResultData imResultData = getResponseData(new TypeToken<JstyleResponse<ImResultData>>() {
                }.getType(), message);
                List<ImResultData.BindersBean> list = imResultData.getBinders();
                if (list.size() != 0) DataDbHelper.getInstance().getBindersDao().insert(list);
                List<ImResultData.GroupsBean> listGroup = imResultData.getGroups();
                if (listGroup.size() != 0)
                    DataDbHelper.getInstance().getGroupsDao().insert(listGroup);
                Log.i(TAG, "resolveData: " + imResultData.getBinders().size());
                break;
            case JstyleConst.TYPE_BIND:
                BindContactData bindDeviceData = getResponseData(new TypeToken<JstyleResponse<BindContactData>>() {
                }.getType(), message);
                ContactUtils.addContact(context, bindDeviceData);
                break;
            case JstyleConst.TYPE_UNBIND:
                BindContactData unBindDeviceData = getResponseData(new TypeToken<JstyleResponse<BindContactData>>() {
                }.getType(), message);
                ContactUtils.deleteContact(context, unBindDeviceData);
                break;
            case JstyleConst.TYPE_PONG:

                break;
            case JstyleConst
                    .TYPE_CONNECT:
                ConnectResponse connectResponse = getResponseData(new TypeToken<JstyleResponse<ConnectResponse>>() {
                }.getType(), message);
                if (connectResponse.getResult().equals("success")) {
                    startHeartPackage();
                    startUploadHistory();
                }
                break;
            case JstyleConst
                    .TYPE_REGISTER:
                RegisterResponse response = getResponseData(new TypeToken<JstyleResponse<RegisterResponse>>() {
                }.getType(), message);
                String watchId = response.getWatchId();
                Log.i(TAG, "resolveData: watchId " + watchId);
                SharedPreferenceUtils.setSpString(SharedPreferenceUtils.watchId, watchId);
                sendMsg(NetSendUtils.connect(watchId));
               MyApp.getInstance().login();
                break;
            case JstyleConst.TYPE_DATA:
                HistoryDataResponse historyDataResponse = getResponseData(new TypeToken<JstyleResponse<HistoryDataResponse>>() {
                }.getType(), message);

                break;
            case JstyleConst.TYPE_GPSDATA:
                break;
            case JstyleConst.TYPE_SN:
                ElectronicFenceData electronicFenceData = getResponseData(new TypeToken<JstyleResponse<ElectronicFenceData>>() {
                }.getType(), message);
                createGeoFence(electronicFenceData, from);
                break;
            case JstyleConst.TYPE_DelSn:
                ElectronicFenceData deleteData = getResponseData(new TypeToken<JstyleResponse<ElectronicFenceData>>() {
                }.getType(), message);
                deleteGeoFence(deleteData.getId(), from);
                break;
            case JstyleConst.TYPE_RTBP:
            case JstyleConst.TYPE_RTHR:
            case JstyleConst.TYPE_RTECG:
            case JstyleConst.TYPE_RTSPO2:
                startRealTimeData(type, message, from);
                break;
            case JstyleConst.TYPE_SETCLOCK:
                SetClockData clockData = getResponseData(new TypeToken<JstyleResponse<SetClockData>>() {
                }.getType(), message);

                setClockData(clockData, from);

                break;
            case JstyleConst.TYPE_DELCLOCK:
                DeleteClockData deleteClock = getResponseData(new TypeToken<JstyleResponse<DeleteClockData>>() {
                }.getType(), message);
                deleteClock(deleteClock.getId(), from);
                break;
            case JstyleConst.TYPE_SetWifi:
                WifiSetData wifiSetData = getResponseData(new TypeToken<JstyleResponse<WifiSetData>>() {
                }.getType(), message);
                WifiConnectUtils wifiConnectUtils = new WifiConnectUtils(context);
                wifiConnectUtils.connectWifi(wifiSetData.getSsid(), wifiSetData.getPassword(), WifiConfiguration.SECURITY_TYPE_PSK);
                sendMsg(NetSendUtils.resultResponse(JstyleConst.TYPE_SetWifi, wifiSetData.getId(), JstyleConst.Success, from));
                break;
            case JstyleConst.TYPE_MONI:
                MoniData moniData = getResponseData(new TypeToken<JstyleResponse<MoniData>>() {
                }.getType(), message);
                String phone = moniData.getPhone();
                MoniDataUtils.getInstance().addPhone(phone);
                break;
            case JstyleConst.TYPE_Updatec:
            case JstyleConst.TYPE_Addc:
                ContactData contactData = getResponseData(new TypeToken<JstyleResponse<ContactData>>() {
                }.getType(), message);
                String id = contactData.getId();
                String phoneNumber = contactData.getPhone();
                String name = contactData.getName();
                ContactData contactDataTemp = DataDbHelper.getInstance(context).getContactDataDao().findContact(id);
                if (contactDataTemp == null) {
                    ContactUtils.addContact(context, contactData);
                } else {
                    long contactId = contactDataTemp.getContactId();
                    contactDataTemp.setName(name);
                    contactDataTemp.setPhone(phoneNumber);
                    ContactUtils.updateContact(context, contactId, phoneNumber, name);
                    DataDbHelper.getInstance(context).getContactDataDao().updateContact(contactDataTemp);
                }

                break;
            case JstyleConst.TYPE_RTL:
                LocationUtils.getInstance().setFrom(from);
                startLocation();
                break;
            case JstyleConst.TYPE_Delc:
                DeleteContact deleteContact = getResponseData(new TypeToken<JstyleResponse<DeleteContact>>() {
                }.getType(), message);
                String deleteId = deleteContact.getId();
                ContactData contactDataDelete = DataDbHelper.getInstance(context).getContactDataDao().findContact(deleteId);
                if (contactDataDelete == null) return;
                long contactId = contactDataDelete.getContactId();
                ContactUtils.deleteContact(context, contactId);
                DataDbHelper.getInstance(context).getContactDataDao().deleteContact(deleteId);
                break;
            case JstyleConst.TYPE_Find:
                toAlert(message);
                break;
            case JstyleConst.TYPE_Shutdown:
                toShutDown();
                break;
            case JstyleConst.TYPE_StepGoal:
                StepGoal stepGoal = getResponseData(new TypeToken<JstyleResponse<StepGoal>>() {
                }.getType(), message);
                int step = stepGoal.getGoal();
                if (step <= 0) {
                    sendMsg(NetSendUtils.resultResponse(type, JstyleConst.Failure, from));
                } else {
                    RealTimeData realTimeData = DataDbHelper.getInstance(context).getRealTimeStepDao().getLastRealTimeStep(DateUtils.getDefaultToday(new Date()));
                    int realTimeStep = realTimeData.getSteps();
                    //两个提醒都还没完成的时候，设置目标值小于现有的步数时，会出现一有步数变化马上提醒完成100%
                    //需要设置目标值小于现有的步数时 设置两个提醒日期都为今天（等看需求实现）
                    if (step / 2 > realTimeStep) {
                        SharedPreferenceUtils.setSpString(SharedPreferenceUtils.KEY_StepGoalTips1, "");
                        SharedPreferenceUtils.setSpString(SharedPreferenceUtils.KEY_StepGoalTips2, "");
                    } else if (step > realTimeStep) {
                        SharedPreferenceUtils.setSpString(SharedPreferenceUtils.KEY_StepGoalTips2, "");
                    }
                    SharedPreferenceUtils.setSpInteger(SharedPreferenceUtils.KEY_StepGoal, step);
                }

                Log.i(TAG, "resolveData: " + step);


                break;
            case JstyleConst.TYPE_Psm:
                PsmData psmData = getResponseData(new TypeToken<JstyleResponse<PsmData>>() {
                }.getType(), message);
                String startup = psmData.getStartup();
                String shutdown = psmData.getShutdown();
                Log.i(TAG, "resolveData: " + startup + " " + shutdown);
                SharedPreferenceUtils.setSpString(SharedPreferenceUtils.KEY_PsmStart, startup);
                SharedPreferenceUtils.setSpString(SharedPreferenceUtils.KEY_PsmShunDowm, shutdown);
                sendMsg(NetSendUtils.resultResponse(type, JstyleConst.Success, from));
                break;
            case JstyleConst.TYPE_Callr:
                CallLogs callLog = getResponseData(new TypeToken<JstyleResponse<CallLogs>>() {
                }.getType(), message);
                String time = callLog.getTime();
                List<UploadCallLogs> callLogs = ContactUtils.getCallLogs(context, time);
                //一次取20条。websocket一次不能传太多数据，需要分开发
                Observable.fromIterable(callLogs).buffer(20).subscribe(new Observer<List<UploadCallLogs>>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(List<UploadCallLogs> list) {
                        sendMsg(NetSendUtils.uploadCallLogs(list));
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });

                break;
            case JstyleConst.TYPE_Smsq:
                CallLogs sms = getResponseData(new TypeToken<JstyleResponse<CallLogs>>() {
                }.getType(), message);
                String lastTime = sms.getTime();
                List<SmsInfo> smsInfos = ContactUtils.getAllSmsInfo(context, lastTime);
                //一次取20条。websocket一次不能传太多数据，需要分开发
                Observable.fromIterable(smsInfos).buffer(20).subscribe(new Observer<List<SmsInfo>>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(List<SmsInfo> list) {
                        sendMsg(NetSendUtils.uploadSmsInfos(list));
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });

                break;
        }
    }

    private void toAlert(String message) {
        FindWatchBean findWatchBean = getResponseData(new TypeToken<JstyleResponse<FindWatchBean>>() {
        }.getType(), message);
        int state = findWatchBean.getState();
        if (state == 1) {
            toAlert();
        } else {
            Activity showActivity = MyApp.getInstance().getShowActivity();
            if (showActivity instanceof FindPhoneActivity) {
                showActivity.finish();
            }
        }
    }

    private void clearData() {
        DataDbHelper.getInstance().getGroupsDao().deleteAllGroup();
        DataDbHelper.getInstance().getBindersDao().deleteAllBinders();
        ContactUtils.deleteAllContact(context);
    }

    /**
     * 手表提醒（震动？铃声？）
     */
    private void toAlert() {
        //to do
        Utils.wakeUpAndUnlock(context);
        startActivity(FindPhoneActivity.class, 0, "");
    }

    private void toShutDown() {
        Utils.shutdown(context);
    }

    private void deleteGeoFence(String id, String from) {
        sendMsg(NetSendUtils.resultResponse(JstyleConst.TYPE_DelSn, id, JstyleConst.Success, from));
    }

    /**
     * 删除闹钟
     *
     * @param id
     */
    private void deleteClock(String id, String from) {
        ClockUtils.getInstance().cancelClock(context, Long.valueOf(id));
        sendMsg(NetSendUtils.resultResponse(JstyleConst.TYPE_DELCLOCK, id, JstyleConst.Success, from));
        DataDbHelper.getInstance(context).getClockDataDao().deleteClock(Long.valueOf(id));
    }

    /**
     * 设置闹钟
     *
     * @param clockData
     */
    private void setClockData(SetClockData clockData, String from) {
        String id = clockData.getId();
        String time = clockData.getClock();
        String state = clockData.getState();
        String cycle = clockData.getCycle();
        int type = clockData.getType();
        String[] timeArray = time.split(":");
        int hour = Integer.valueOf(timeArray[0]);
        int minute = Integer.valueOf(timeArray[1]);
        boolean enable = state.equals("opened");
        JstyleClock jstyleClock = new JstyleClock();
        jstyleClock.setId(Long.valueOf(id));
        jstyleClock.setClockType(type);
        jstyleClock.setHour(hour);
        jstyleClock.setMinute(minute);
        jstyleClock.setCycle(cycle);
        jstyleClock.setEnable(enable);
        if (enable) {
            ClockUtils.getInstance().setClock(context, jstyleClock);
        } else {
            ClockUtils.getInstance().cancelClock(context, Long.valueOf(clockData.getId()));
        }

        DataDbHelper.getInstance(context).getClockDataDao().insert(jstyleClock);
        sendMsg(NetSendUtils.resultResponse(JstyleConst.TYPE_SETCLOCK, id, JstyleConst.Success, from));
    }

    void createGeoFence(ElectronicFenceData electronicFenceData, String from) {
        int mode = electronicFenceData.getWarn();
        int geoFenceMode = GeoFence.STATUS_IN;
        if (mode == 1) {
            geoFenceMode = GeoFence.STATUS_IN;
        } else if (mode == 2) {
            geoFenceMode = GeoFence.STATUS_OUT;
        } else {
            geoFenceMode = GeoFence.STATUS_IN | GeoFence.STATUS_OUT;
        }
        GeoFenceUtils geoFenceUtils = new GeoFenceUtils(context, geoFenceMode);
        String id = electronicFenceData.getId();
        if (!TextUtils.isEmpty(id)) {
            geoFenceUtils.remove(id);
        }
        geoFenceUtils.createGeoFence(Double.valueOf(electronicFenceData.getLat()), Double.valueOf(electronicFenceData.getLng())
                , electronicFenceData.getRadius(), electronicFenceData.getId());
        geoFenceUtils.setGeoFenceListener(new GeoFenceListener() {
            @Override
            public void onGeoFenceCreateFinished(List<GeoFence> list, int errorCode, String s) {
                String result = "";
                if (errorCode == GeoFence.ADDGEOFENCE_SUCCESS) {//判断围栏是否创建成功
                    Log.i(TAG, "onGeoFenceCreateFinished: success");
                    result = JstyleConst.Success;
                    //geoFenceList是已经添加的围栏列表，可据此查看创建的围栏
                } else {
                    result = JstyleConst.Failure;
                    Log.i(TAG, "onGeoFenceCreateFinished: failed");
                }
                sendMsg(NetSendUtils.resultResponse(JstyleConst.TYPE_SN, id, result, from));
            }

        });
    }

    void startRealTimeData(String type, String message, String from) {

        RealTimeMeasureCmd realTimeMeasureCmd = getResponseData(new TypeToken<JstyleResponse<RealTimeMeasureCmd>>() {
        }.getType(), message);
        Log.i(TAG, "startRealTimeData: " + realTimeMeasureCmd.getDuration() + " " + type);
        int time = realTimeMeasureCmd.getDuration();
        int state = realTimeMeasureCmd.getState();
        if (state == 2) {
            BleData actionData = new BleData();
            actionData.setAction(ActionData.StopMeasure);
            RxBus.getInstance().post(actionData);
            return;
        }
        if (isMeasuring) return;
        isMeasuring = true;
        Utils.wakeUpAndUnlock(context);
        switch (type) {
            case JstyleConst.TYPE_RTBP:
                startActivity(BpMeasureActivity.class, time, from);
                break;
            case JstyleConst.TYPE_RTHR:
                startActivity(HeartRateMeasureActivity.class, time, from);
                break;
            case JstyleConst.TYPE_RTECG:
                startActivity(EcgMeasureActivity.class, time, from);
                break;
            case JstyleConst.TYPE_RTSPO2:
                startActivity(Spo2MeasureActivity.class, time, from);
                break;
        }
    }

    void startActivity(Class measureActivity, int time, String from) {
        Activity activity = MyApp.getInstance().getShowActivity();
        Intent intent = new Intent(activity, measureActivity);
        intent.putExtra(BaseActivity.KEY_MeasureTime, time);
        intent.putExtra(BaseActivity.KEY_MeasureFrom, from);
        activity.startActivity(intent);
    }

    private <T> T getResponseData(Type typeR, String msg) {
        Gson gson = new Gson();
        JstyleResponse<T> responseJstyleResponse = gson.fromJson(msg, typeR);
        return responseJstyleResponse.getData();
    }

    private final static int RECONNECT_INTERVAL = 5;

    private void startReconnectWifiObservable() {

        //  if (reconnectWifiObservable != null && !reconnectWifiObservable.isDisposed()) return;
        long delay = (long) (RECONNECT_INTERVAL + Math.random() * 10);
        Log.i(TAG, "startReconnectWifiObservable: delay " + delay);
        Observable.timer(delay, TimeUnit.SECONDS).compose(SchedulersTransformer.<Long>io2MainObservable()).subscribe(new Observer<Long>() {
            @Override
            public void onSubscribe(Disposable d) {
                reconnectWifiObservable = d;
            }

            @Override
            public void onNext(Long aLong) {

                if (webSocketClient != null && webSocketClient.isClosed()) {
                    startReconnectService();
                }
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });
    }

    public void startReconnectService() {
        boolean isAvailable=NetWorkUtil.isNetworkConnected(context);
        Log.i(TAG, "startReconnectService: isNetworkConnected "+isAvailable);
         if(!isAvailable)return;
        webSocketClient.reconnect();
        Log.i(TAG, "startReconnectService: startReconnect");
    }

    /**
     * 心跳包
     */
    private void startHeartPackage() {
        Log.i(TAG, "heartPackageObservable: start ");
        ClockUtils.getInstance().setHeartPackageClock(context);
//        if (heartPackageObservable != null && !heartPackageObservable.isDisposed()) return;
//        Observable.interval(0, 8, TimeUnit.MINUTES).compose(SchedulersTransformer.<Long>io2MainObservable()).subscribe(new Observer<Long>() {
//            @Override
//            public void onSubscribe(Disposable d) {
//                heartPackageObservable = d;
//            }
//
//            @Override
//            public void onNext(Long aLong) {
//                Log.i(TAG, "startHeartPackage onNext: " + aLong);
//                startLocation();
//
//            }
//
//            @Override
//            public void onError(Throwable e) {
//                Log.i(TAG, "onError: " + e.getMessage());
//            }
//
//            @Override
//            public void onComplete() {
//
//            }
//        });
    }

    private void startUploadHistory() {
        Log.i(TAG, "startUploadHistory: start ");
        if (uploadHistoryObservable != null && !uploadHistoryObservable.isDisposed()) return;
        Observable.interval(0, 30, TimeUnit.MINUTES).compose(SchedulersTransformer.<Long>io2MainObservable()).subscribe(new Observer<Long>() {
            @Override
            public void onSubscribe(Disposable d) {
                uploadHistoryObservable = d;
            }

            @Override
            public void onNext(Long aLong) {
                Log.i(TAG, "startUploadHistory onNext: " + aLong);
                HistoryDataUploadUtils.uploadData();

            }

            @Override
            public void onError(Throwable e) {
                Log.i(TAG, "onError: " + e.getMessage());
            }

            @Override
            public void onComplete() {

            }
        });
    }

    private void startLocation() {
        LocationUtils locationUtils = LocationUtils.getInstance();
        locationUtils.startLocation();

    }

    WebSocket webSocketSend;

    public void sendMsgO(String msg) {
        if (TextUtils.isEmpty(msg)) return;
        Log.i(TAG, "sendMsg: " + msg);
        webSocketSend.send(msg);

    }

    public void sendMsg(String msg) {
        //  webSocketSend.send(msg);
        Log.i(TAG, "sendMsg: 发送之前 "+msg);
//        if(!TextUtils.isEmpty(msg)){
//            try {
//                msg=AesTest.Encrypt(msg);
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//        }
        if (webSocketClient.getConnection().isClosed()) {
            Log.i(TAG, "sendMsg: reconnect");
            startReconnectService();
            return;
        }
        Log.i(TAG, "sendMsg: " + msg);
        if (webSocketClient.getConnection().isOpen()) {
            if (TextUtils.isEmpty(msg)) return;
            webSocketClient.send(msg);
        }
    }

    public boolean isConnected() {
        return webSocketClient.getConnection().isOpen();
    }

    private void unsubscribe(Disposable disposable) {
        if (disposable != null && !disposable.isDisposed()) {
            disposable.dispose();
        }
    }
}
